const Koa = require('koa');
const Fs = require('node:fs');
const Https = require('node:https');
const net = require('node:net');
const Http = require('node:http');

const {
    getClientIp,
    AutoReconnectWebSocket,
    SerialPortManager,
    MainConfig
} = require("./Tool/index");

const {join} = require("path");

const app = new Koa();

const _static = require('koa-static');

// 解决跨域问题
const Cors = require('koa2-cors');

const SocketIO = require('socket.io');


// 获取当前环境变量模式
const Dotenv = require('dotenv');

const EnvironmentMode = process.argv[2] == "--mode" ? process.argv[3] : "pro";

// 启动Http服务
const _Http = Http.createServer(app.callback())

const ioHttp = new SocketIO.Server(_Http, {
    cors: {
        origin: "*",
    }
});

let ioHttpSocket = null;


let SelectObj = MainConfig()["Default"]

Dotenv.config({
    path: `./.env.${EnvironmentMode}`,
});

const {koaBody} = require("koa-body");

const RouterResponse = require("./Middleware/RouterResponse");

const _logs = require('./logs/index');

// 引入路由
const indexRouter = require('./Router/index');


const UeSocket = new AutoReconnectWebSocket({
    url: `ws://127.0.0.1:${MainConfig()["UE_WebSocket_Port"]}`, options: {
        onopen: () => {
            _logs.normal.info("UeWebSocket成功");

            setTimeout(() => {
                ToUe({
                    FuncName: "SysButtonControl", Args: {
                        Name: SelectObj["Location"]
                    }
                })
            }, 1500)
        }, onclose: () => {
        }, onmessage: (message) => {
            _logs.normal.info("收到UE消息", message.data);
        }
    }
});


/**
 * @description: 根据指令操作数据传输
 * @author: 王琛
 * @Date: 2025-09-05 15:30:44
 * @param {*}
 * @return {*}
 */
function CommandTransmission(Instruction) {
    try {
        // 获取指令配置
        const CommandParameters = MainConfig()["CommandParameters"];
        // 获取当前指令
        const CurrentCommand = CommandParameters[Instruction]

        if (!CurrentCommand) throw new Error(`未找到对应的指令配置:${Instruction}`);

        _logs.normal.info(`检测到信息配置:${JSON.stringify(CurrentCommand)}`);

        // 判断是否有串口指令
        if (CurrentCommand?.RelayInstruction?.length || CurrentCommand?.CloseRelayInstruction?.length) {

            // 先关掉所有继电器
            if (CurrentCommand?.CloseRelayInstruction && CurrentCommand?.CloseRelayInstruction?.length) _SerialPort.send(`G${CurrentCommand.CloseRelayInstruction.join("G")}`);

            setTimeout(() => {

                const _IsClose = CurrentCommand["MandatorOPption"] ? "K" : SelectObj[CurrentCommand.KeyName] != CurrentCommand["Name"] ? "G" : "K";
                // 拼接继电器指令
                let RelayInstruction = `${_IsClose}${CurrentCommand.RelayInstruction.join(_IsClose)}`;

                if (CurrentCommand.RelayInstruction?.length) _SerialPort.send(RelayInstruction);


            }, MainConfig()["CommandInterval"] || 200)
        }

        // 判断是否允许取消
        if (CurrentCommand["MandatorOPption"]) {

            SelectObj[CurrentCommand.KeyName] = CurrentCommand["Name"];

        } else {
            SelectObj[CurrentCommand.KeyName] = SelectObj[CurrentCommand.KeyName] ? "" : CurrentCommand["Name"];
        }
        // 发送给UE切换视频
        ToUe({
            FuncName: "SysButtonControl", Args: {
                Name: CurrentCommand.UeName
            }
        });
        // 通知前端更新状态
        ioHttpSocket.emit("message", {
            FuncName: "SelectState", Args: SelectObj
        })


    } catch (e) {
        _logs.normal.error(e.message)
    }
}

// 串口连接
const _SerialPort = new SerialPortManager({
    path: MainConfig()["SerialPortName"],
    baudRate: 9600,
    dataBits: 8,
    stopBits: 1,
    parity: 'none',
    autoOpen: true,
    flowControl: false,
    onmessage: (msg) => {

        const _Str_Msg = msg.toString().trim();
        // 如果是空值则不处理
        if (!_Str_Msg) return;
        setTimeout(() => {
            CommandTransmission(_Str_Msg)
        }, MainConfig()["CommandInterval"] || 200)

    }, Init: () => {
        const BtnList = Object.values(MainConfig()["CommandParameters"]);
    }
});

/**
 * @description: 统一处理错误函数
 * @author: 王琛
 * @Date: 2023-09-18 15:59:34
 * @param {*}
 * @return {*}
 */
async function UnifiedErr(fn, errFn) {
    try {
        fn && await fn()
    } catch (e) {
        errFn && errFn(e.message);
        _logs.err.error(`统一处理错误:${e.message}`);
    }
}


// 同意处理函数
app.use(async (ctx, next) => {
    ctx.IoSocket = ioHttp;
    // 挂载连接ue的websocket对象
    ctx._UeSocket = UeSocket;
    // 挂在日志插件
    ctx._logs = _logs;
    // 挂在统一处理错误函数
    ctx.UnifiedErr = UnifiedErr;
    _logs.normal.info(`请求信息:${getClientIp(ctx.req)}`);
    // 挂在数据库插件
    await next();
});

Date.prototype.format = function (format) {
    var o = {
        "M+": this.getMonth() + 1, //month
        "d+": this.getDate(), //day
        "h+": this.getHours(), //hour
        "m+": this.getMinutes(), //minute
        "s+": this.getSeconds(), //second
        "q+": Math.floor((this.getMonth() + 3) / 3), //quarter
        "S": this.getMilliseconds() //millisecond
    }
    if (/(y+)/.test(format)) format = format.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o) if (new RegExp("(" + k + ")").test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
    return format;
}

// 配置各种中间件
app.use(Cors()).use(koaBody()).use(RouterResponse());
// 配置路由独享
app.use(indexRouter.routes(), indexRouter.allowedMethods());
// 创建静态资源目录
app.use(_static(join('./public'), {
    gzip: true, defer: true,
}));
// 获取https的证书
const options = {
    key: Fs.readFileSync('./ssl/www.zhangduo-tech.com.key'), cert: Fs.readFileSync('./ssl/www.zhangduo-tech.com.pem')
};


ioHttp.on('connection', (socket) => {
    _logs.normal.info('有新的Socket连接', socket.id);

    ioHttpSocket = socket;

    socket.on("message", (message) => {

        _logs.normal.info("收到Socket消息", JSON.stringify(message));

        const {FuncName, Args} = message;

        if (FuncName === "SysButtonControl" && Args?.Instruction) CommandTransmission(Args?.Instruction);

        if (FuncName === "GetBtnConfig") {
            socket.emit("message", {
                FuncName: "GetBtnConfig", Args: MainConfig()["CommandParameters"]
            })
            socket.emit("message", {
                FuncName: "SelectState", Args: SelectObj
            })
        }
    })
});

/**
 * @description: 描述
 * @author: 王琛
 * @Date: 2025-09-08 20:49:45
 * @param {*}
 * @return {*}
 */
function ToUe({FuncName, Args}) {
    try {
        UeSocket.send(JSON.stringify({
            FuncName, Args
        }));
    } catch (e) {
        console.error('%c大屏发送报错报错-20:49:45', 'color:#fff;fontSize:15px;background:#993366;padding:2px 5px;border-radius:6px', e.message);
    }

}

_Http.listen(MainConfig()["LocalServerPort"], (err) => {
    if (err) {
        _logs.err.error(`Http启动失败${err}`);
        return;

    }
    _logs.normal.info(`Http启动成功,监听端口号${MainConfig()["LocalServerPort"]}`);
});

